package com.atguigu.gmall.activity.receiver;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;

/**
 * @author atguigu-mqx
 */
@Component
public class SeckillReceiver {

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsService seckillGoodsService;

    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_1, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_1}
    ))
    public void importDataToRedis(String msg, Message message, Channel channel) {
        try {
            System.out.println(msg);
            // 查询秒杀商品： 当天时间{select date_format(start_time,'%Y-%m-%d') from seckill_goods}
            // 状态   status = 1 stock_count > 0;
            QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
            seckillGoodsQueryWrapper.eq("status","1");
            seckillGoodsQueryWrapper.gt("stock_count",0);
            seckillGoodsQueryWrapper.eq("date_format(start_time,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);

            //  获取到当前秒杀商品之后，循环遍历到缓存中.
            if (!CollectionUtils.isEmpty(seckillGoodsList)){
                for (SeckillGoods seckillGoods : seckillGoodsList) {
                    //  使用的数据类型 hash  hset key field value
                    String activityKey = RedisConst.SECKILL_GOODS;
                    //  判断当前商品是否在缓存中存在，如果存在，则不需要再次放入!
                    Boolean result = this.redisTemplate.opsForHash().hasKey(activityKey, seckillGoods.getSkuId().toString());
                    //  有这个商品
                    if (result){
                        //  结束当前循环
                        //  break;//    结束整个循环    continue; 结束当前本次循环  return 方法都停了！
                        continue;
                    }
                    this.redisTemplate.opsForHash().put(activityKey,seckillGoods.getSkuId().toString(),seckillGoods);
                    //  需要将商品的剩余库存数，放入redis - list
                    for (Integer i = 0; i < seckillGoods.getStockCount(); i++) {
                        //  key=seckill:stock:skuId  skuId
                        this.redisTemplate.opsForList().leftPush(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId(),seckillGoods.getSkuId().toString());
                    }

                    //  使用redis 订阅、发布 同步状态位！ 初始化状态位都是 skuId:1
                    this.redisTemplate.convertAndSend("seckillpush",seckillGoods.getSkuId()+":1");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        //  手动确认消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);

    }

    //  监听下单成功之后的用户队列!
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER),
            key = {MqConst.ROUTING_SECKILL_USER}
    ))
    public void seckillOrder( UserRecode userRecode,Message message,Channel channel){
        try {
            //  判断
            if (userRecode!=null){
                //  调用方法.
                seckillGoodsService.seckillOrder(userRecode.getSkuId(),userRecode.getUserId());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //  手动确认消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);

    }

    //  删除数据.
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_18, durable = "true", autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_18}
    ))
    public void clearData(String msg, Message message, Channel channel){
        try {
            System.out.println(msg);
            //  获取到skuId, 秒杀结束. 判断当前系统时间与秒杀结束时间做比较.
            //  构建查询条件.
            QueryWrapper<SeckillGoods> seckillGoodsQueryWrapper = new QueryWrapper<>();
            seckillGoodsQueryWrapper.eq("status",1);
            //  格式：yyyy-MM-dd HH:mm:ss
            seckillGoodsQueryWrapper.lt("end_time",new Date());
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(seckillGoodsQueryWrapper);
            //  循环遍历
            if (!CollectionUtils.isEmpty(seckillGoodsList)){
                for (SeckillGoods seckillGoods : seckillGoodsList) {
                    //  删除剩余库存数
                    this.redisTemplate.delete(RedisConst.SECKILL_STOCK_PREFIX+seckillGoods.getSkuId());
                }
            }
            //  删除数据.
            //  有缓存所有秒杀商品数据.
            this.redisTemplate.delete(RedisConst.SECKILL_GOODS);
            //  删除预下单数据.
            this.redisTemplate.delete(RedisConst.SECKILL_ORDERS);
            //  真正下单的数据.
            this.redisTemplate.delete(RedisConst.SECKILL_ORDERS_USERS);

            //  更新一下数据库的秒杀商品状态.
            SeckillGoods seckillGoods = new SeckillGoods();
            seckillGoods.setStatus("0");
            this.seckillGoodsMapper.update(seckillGoods,seckillGoodsQueryWrapper);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //  手动确认消息.
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
}
